// Copyright(c) Sonosemi Medical Ltd. Embedded Software Team.
// Author: Zhang Yisong(zhangyisong@sonosemi.com)

#pragma once


#if __has_include("pw_work_queue/work_queue.h")
#include "pw_work_queue/work_queue.h"
#if __has_include("pw_thread/detached_thread.h")
#include "pw_thread/detached_thread.h"
#include "pw_thread/options.h"
#include "pw_thread_zephyr/options.h"
#endif
#endif
#include "active/active_initializer.hpp"
#include "cib/cib_connect.hpp"
#include "internal/active_service.hpp"
namespace active {

namespace internal {
enum class Supported {
  baremetal,
  workqueue,
};

} // namespace internal

namespace Scheduler {

#ifndef CONFIG_ACTIVE_MAX_WORK_QUEUE_ITEMS
#define CONFIG_ACTIVE_MAX_WORK_QUEUE_ITEMS 20
inline constexpr auto kMaxWorkQueueItems = CONFIG_ACTIVE_MAX_WORK_QUEUE_ITEMS;
#endif // !CONFIG_ACTIVE_MAX_WORK_QUEUE_ITEMS
#ifndef CONFIG_ACTIVE_WQ_STACK_SIZE
#define CONFIG_ACTIVE_WQ_STACK_SIZE 512
#endif // !CONFIG_ACTIVE_WQ_STACK_SIZE
#define CONFIG_ACTIVE_WQ_STACK_SIZE 512
struct BareMetal {
  static auto Run() {
    while (true) {
      ProcessQueuedEvents();
    }
  }
};

struct WorkQueue {
  static auto WorkQueueOption() -> pw::thread::Options & {
    constexpr int kPriority = pw::thread::zephyr::config::kDefaultPriority;
    constexpr int kStackSize = CONFIG_ACTIVE_WQ_STACK_SIZE;
    static pw::thread::zephyr::StaticContextWithStack<kStackSize>
        example_thread_context;
    static auto option = pw::thread::zephyr::Options(example_thread_context)
        .set_priority(kPriority);
    return option;
  }
  static auto Submit() -> void { m_work_queue.CheckPushWork(WorkHandler); }
  static auto Run() -> void {
    pw::thread::DetachedThread(WorkQueueOption(), m_work_queue);
    cib::Connect<service::QueuedEvent>([]() { Submit(); });
  }

private:
  static auto WorkHandler() -> void { ProcessQueuedEvents(); }
  inline static pw::work_queue::WorkQueueWithBuffer<kMaxWorkQueueItems>
      m_work_queue;
};

}; // namespace Scheduler

template <typename TScheduler> static inline auto Schedule() {
  TScheduler::Run();
}

} // namespace active